package com.framework.minio.controller;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.framework.minio.service.MinioService;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.common.utils.constant.FileType;
import com.common.utils.tool.ContentTypeUtil;
import com.common.model.exception.FileNoSupportException;
import com.common.model.result.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * 描述：
 * minio 文件直接访问接口
 * @author xianggj
 * @Date 2021/9/3 18:47
 **/
@RestController
@RequestMapping("minio")
@ApiSort(15)
@Slf4j
@Api(value = "minio预览服务", tags="minio预览服务")
public class MinioController {

    @Autowired
    private MinioService minioService;

    /**
     * 预览图片
     *  访问方式
     *  http://<ip:port>/hn/minio/view/hnneng/hn_data/138cb562d19842bc8fbef89c5738c8d1.jpg
     * @param
     * @return
     */
    @ApiOperation(value = "文件预览",notes = "仅仅支持pdf,图片和视频")
    @GetMapping(value = "/download/**")
    public void viewFile(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String path = extractPathFromPattern(request);
        InputStream inputStream = null;
        OutputStream outputStream = null;
        String bucketName = "";
        String fileName = "";
        if (StringUtils.isNotEmpty(path)){
            bucketName = StringUtils.substringBefore(path, "/");
            fileName = StringUtils.substringAfter(path, "/");
        }
        try {
            FileType fileType = FileType.enumOf(fileName);
            if(FileType.PDF.equals(fileType)){
                response.setContentType(MediaType.APPLICATION_PDF_VALUE);
            }else if(FileType.HTML.equals(fileType)){
                response.setContentType(MediaType.TEXT_HTML_VALUE);
            } else { //只特殊处理pdf和html 其他文件通通下载
                response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            }
            inputStream = minioService.getFileStream(bucketName, fileName);
            outputStream = response.getOutputStream();
            IoUtil.copy(inputStream, outputStream);
            response.flushBuffer();
        } catch (Exception e) {
            log.error("预览失败:" + e.getMessage());
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     *  把指定URL后的字符串全部截断当成参数
     *  这么做是为了防止URL中包含中文或者特殊字符（/等）时，匹配不了的问题
     * @param request
     * @return
     */
    private static String extractPathFromPattern(final HttpServletRequest request) {
        String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
        String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
    }
    /**
     * 上传复杂文件
     * @param file
     * @return
     */
    @ApiOperation(value = "上传文件到minio",notes = "上传图片等类型文件")
    @ApiImplicitParam(name = "path", value = "文件夹（默认为test）")
    @PostMapping("/uploadFile")
    public Result uploadComplexFile(MultipartFile file, String path) {
        try {
            String fileName = file.getOriginalFilename();
            String ext = StringUtils.substringAfterLast(fileName, ".");
            FileType fileType = FileType.enumOf(ext);
            if (fileType == null){
                throw new FileNoSupportException("文件不支持");
            }
            String url = minioService.putFile(StrUtil.isBlank(path)?"test":path ,file.getInputStream(),
                     ext, ContentTypeUtil.getContentType(ext));
            return Result.succeed(url, "上传成功");

        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed( "上传失败");
        }
    }

}
